#include "CTween.h"

Int32 CALLBACKTYPE GetElasticValue(
    /* [in] */ Int32 fromValue,
    /* [in] */ Int32 toValue,
    /* [in] */ Millisecond32 elaspedTime,
    /* [in] */ Millisecond32 durationTime,
    /* [in] */ EaseType easeType)
{
    double dx = (double)toValue - fromValue;
    double delta = 0.0;
    double p = (double)durationTime * 0.3;
    double ratio = ((double)elaspedTime) / durationTime;

    switch (easeType) {
        case EaseType_In:
            if (0 == elaspedTime) {
                break;
            }
            else if (elaspedTime == durationTime) {
                delta = dx;
                break;
            }
            else {
                double s = p / 4;
                ratio -= 1.0;
                delta = -(dx * pow(2, 10 * ratio)
                        * sin((ratio * durationTime - s) * 2 * GFX_PI / p));
            }

            break;

        case EaseType_Out:
            if (0 == elaspedTime) {
                break;
            }
            else if (elaspedTime == durationTime) {
                delta = dx;
                break;
            }
            else {
                double s = p / 4;
                delta = dx * pow(2, -ratio * 10)
                        * sin((ratio * durationTime - s) * 2.0 * GFX_PI / p) + dx;
            }

            break;

        case EaseType_InOut: {
            ratio = ratio * 2.0 - 1.0;
            p *= 1.5;
            double s = p / 4;

            if ((elaspedTime << 1) < durationTime) {
                delta = -0.5 * dx * pow(2, 10 * ratio)
                        * sin((ratio * durationTime - s) * 2.0 * GFX_PI / p);
            }
            else {
                delta = dx + dx * 0.5 * pow(2, -10 * ratio)
                        * sin((ratio * durationTime - s) * 2.0 * GFX_PI / p);
            }

            break;
        }

        default:
            assert(0);
    }

    return (Int32)(fromValue + delta);
}
